use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};
use once_cell::sync::OnceCell;
use crate::{
    abstractions::{data::Data, task::TaskAbstraction}, error::ServerError, protocol::{
        task::{SymbolicTask, TaskSignature},
        type_schema::TypeSchema,
    }, workflows::workflow::{
        RunningWorkflow, Workflow, WorkflowRunningStatus::{self, *}
    }
};
pub struct WorkflowManager {
    pub all_tasks: HashMap<String, SymbolicTask>,
    pub all_builtin_taskabs: HashMap<String, Arc<TaskAbstraction>>,
    pub all_workflows: HashMap<String, Workflow>,
    pub task_name_to_id: HashMap<String, String>,
    pub portable_running_workflows: HashMap<u16, RunningWorkflow>,
    pub portable_running_workflows_result: HashMap<u16, Result<Data, ServerError>>,
}
impl WorkflowManager {
    pub fn new() -> Self {
        Self { all_tasks: HashMap::new(), all_builtin_taskabs: HashMap::new(), all_workflows: HashMap::new(), task_name_to_id: HashMap::new(), portable_running_workflows: HashMap::new(), portable_running_workflows_result: HashMap::new() }
    }
    pub fn get_all_tasks(&self) -> &HashMap<String, SymbolicTask> {
        &self.all_tasks
    }
    pub fn clone_all_tasks(&self) -> HashMap<String, SymbolicTask> {
        let mut result = HashMap::new();
        for (name, task) in &self.all_tasks {
            result.insert(name.clone(), task.clone());
        }
        result
    }
    pub fn get_all_workflow_names(&self) -> Vec<String> {
        self.all_workflows.keys().cloned().collect()
    }
    pub fn get_all_workflow_sigs(&self) -> Vec<SymbolicTask> {
        self.all_workflows.values().map(|wf| wf.sig()).collect()
    }
    /// name format: 服务名.任务名
    pub fn add_task(&mut self, task: SymbolicTask, service_id: String) -> Result<(), ServerError> {
        // if self.all_tasks.contains_key(&task.name) {
            // return Err(ServerError::WorkflowError(format!("任务ID已存在: {}，任务名必须唯一", task.name)));
        // }
        self.task_name_to_id.insert(task.name.clone(), service_id);
        self.all_tasks.insert(task.name.clone(), task);
        Ok(())
    }
    pub fn add_builtin_taskabs(&mut self, taskabs: Arc<TaskAbstraction>) -> Result<(), ServerError> {
        if self.all_builtin_taskabs.contains_key(taskabs.name()) {
            return Err(ServerError::WorkflowError(format!("任务ID已存在: {}，任务名必须唯一", taskabs.name())));
        }
        let name = format!("builtin.{}", taskabs.name());
        let task = SymbolicTask::new(name.clone(), taskabs.tin().clone(), taskabs.tout().clone());
        self.all_builtin_taskabs.insert(name.clone(), taskabs);
        self.all_tasks.insert(name, task);
        Ok(())
    }
    pub fn add_workflow(&mut self, workflow: Workflow) -> Result<(), ServerError> {
        let name = workflow.name().clone();
        if self.all_workflows.contains_key(&name) {
            return Err(ServerError::WorkflowError(format!("工作流名已存在: {}", name)));
        }
        self.all_workflows.insert(name, workflow);
        Ok(())
    }
    pub fn add_builtin_workflow(&mut self, workflow: Workflow) -> Result<(), ServerError> {
        let name = format!("builtin.{}", workflow.name());
        if self.all_workflows.contains_key(&name) {
            return Err(ServerError::WorkflowError(format!("工作流名已存在: {}", name)));
        }
        let workflow = workflow.rename(name.clone());
        self.all_workflows.insert(name, workflow.into_portable()?);
        Ok(())
    }
    pub fn get_workflow(&self, name: &str) -> Option<&Workflow> {
        self.all_workflows.get(name)
    }
    pub fn create_portable_running_workflow(&mut self, name: String, port: u16) {
        self.portable_running_workflows.insert(port, RunningWorkflow { port, name, status: Created, progress: vec![], created_at: crate::prelude::now(), completed_at: None, result: None });
    }
    pub fn update_portable_running_workflow(&mut self, port: u16, new_progress: Vec<(String, u64)>, new_status: WorkflowRunningStatus) {
        if let Some(workflow) = self.portable_running_workflows.get_mut(&port) {
            if new_status.completed() {
                workflow.completed_at = Some(crate::prelude::now());
            }
            workflow.progress = new_progress;
            workflow.status = new_status;
        }
    }
    pub fn get_running_workflows(&self) -> HashMap<u16, RunningWorkflow> {
        self.portable_running_workflows.clone()
    }
    pub fn get_running_workflow_progress_status(&self, port: u16) -> Result<RunningWorkflow, ServerError> {
        self.portable_running_workflows.get(&port).map(|x| x.clone()).ok_or(ServerError::WorkflowError(format!("工作流ID(port)不存在: {}", port)))
    }
    pub fn delete_workflow(&mut self, name: &str) -> Result<(), ServerError> {
        self.all_workflows.remove(name);
        Ok(())
    }
    pub fn delete_running_workflow(&mut self, port: u16) -> Result<(), ServerError> {
        self.portable_running_workflows.remove(&port);
        Ok(())
    }
    pub fn protable_running_result_in(&mut self, port: u16, result: Result<Data, ServerError>) {
        self.portable_running_workflows_result.insert(port, result);
    }
    pub fn get_running_workflow_result(&self, port: u16) -> Option<&Result<Data, ServerError>> {
        self.portable_running_workflows_result.get(&port)
    }
}
pub static WORKFLOW_MANAGER: OnceCell<Arc<Mutex<WorkflowManager>>> = OnceCell::new();
pub fn init_workflow_manager() -> Result<(), ServerError> {
    WORKFLOW_MANAGER.set(Arc::new(Mutex::new(WorkflowManager::new()))).map_err(|_| ServerError::SystemErrorStr("工作流管理器初始化失败"))?;
    add_builtin_tasks()?;
    Ok(())
}
use crate::builtins::{calibration::BuiltinCalibration, stimulus_extraction::BuiltinStimulusExtraction, misc::BuiltinMisc, test::BuiltinTest};
pub fn add_builtin_tasks() -> Result<(), ServerError> {
    let mut manager = WORKFLOW_MANAGER.get().unwrap().lock().unwrap();
    let calib = BuiltinCalibration::new();
    manager.add_builtin_taskabs(calib.calib_oc2p())?;
    manager.add_builtin_taskabs(calib.calib_les7p())?;
    let stim = BuiltinStimulusExtraction::new();
    manager.add_builtin_taskabs(stim.light_detection())?;
    manager.add_builtin_taskabs(BuiltinMisc::copy_file_path())?;
    manager.add_builtin_taskabs(BuiltinMisc::list_add_1())?;
    manager.add_builtin_taskabs(BuiltinMisc::int_mul_2())?;
    manager.add_builtin_taskabs(BuiltinTest::test_1())?;
    manager.add_builtin_taskabs(BuiltinTest::test_2())?;
    manager.add_builtin_workflow(BuiltinMisc::calculate_1())?;
    Ok(())
}
